﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Threading;
using System.Windows;
using System.Windows.Forms;
using System.Reflection;

namespace FireEvent
{
    class Program
    {
        static void Main(string[] args)
        {
            string filename = "..\\..\\..\\AppTest\\bin\\debug\\AppTest.exe";
            string formname = "AppTest.Form1";

            Prompt("Launch App...");

            Form f = LaunchApp(filename, formname);

            Prompt("Fire event...");

            DFireEvent d = new DFireEvent(FireEvent);
            object[] par = new object[] { null, EventArgs.Empty};
            object[] o = new object[] { f, "btn_Click_Click", par };
            f.Invoke(d, o);
            are.WaitOne();


        }

        private static void Prompt(string display)
        {
            Console.WriteLine(display);
            Console.ReadLine();
        }
        private static AutoResetEvent are = new AutoResetEvent(false);
        private static BindingFlags Flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance;

        private delegate void DFireEvent(Form f, string methodname, object[] par);

        private static void FireEvent(Form f, string methodname, object[] par)
        {
            Type t = f.GetType();
            MethodInfo mi = t.GetMethod(methodname,Flags);
            mi.Invoke(f, par);
            are.Set();
        }
        private static Form LaunchApp(string filename, string formname)
        {
            Assembly a = Assembly.LoadFrom(filename);
            Type t = a.GetType(formname);
            Form f = (Form)a.CreateInstance(t.FullName);

            AppState aps = new AppState(f);
            ThreadStart ts = new ThreadStart(aps.AppRun);
            Thread thread = new Thread(ts);
            thread.SetApartmentState(ApartmentState.STA);
            thread.IsBackground = true;
            thread.Start();


            return f;
        }
    }

    class AppState
    {
        private Form form;
        public AppState(Form f)
        {
            form = f;
        }

        public void AppRun()
        {
            Application.Run(form);
        }
    }
}
